using MediatR;
using S.O.Api.Write.Application.Command.Medical;
using S.O.Domain.Medical;
using S.O.ErrorCode;
using S.O.Interstructrue.Base;

namespace S.O.Api.Write.Application.Handler.Medical
{
    /// <summary>
    /// 医疗卡挂失处理器
    /// 负责处理医疗卡的挂失业务逻辑
    /// </summary>
    public class LostMedicalCardHandler : IRequestHandler<LostMedicalCardCommand, APIResult<bool>>
    {
        /// <summary>
        /// 医疗卡信息仓储
        /// </summary>
        private readonly IBaseRepository<MedicalCardModel> _medicalCardRepository;
        
        /// <summary>
        /// 患者信息仓储
        /// </summary>
        private readonly IBaseRepository<PatientModel> _patientRepository;
        
        /// <summary>
        /// 日志记录器
        /// </summary>
        private readonly ILogger<LostMedicalCardHandler> _logger;

        /// <summary>
        /// 构造函数，通过依赖注入初始化所需服务
        /// </summary>
        /// <param name="medicalCardRepository">医疗卡信息仓储</param>
        /// <param name="patientRepository">患者信息仓储</param>
        /// <param name="logger">日志记录器</param>
        public LostMedicalCardHandler(
            IBaseRepository<MedicalCardModel> medicalCardRepository,
            IBaseRepository<PatientModel> patientRepository,
            ILogger<LostMedicalCardHandler> logger)
        {
            _medicalCardRepository = medicalCardRepository;
            _patientRepository = patientRepository;
            _logger = logger;
        }

        /// <summary>
        /// 处理医疗卡挂失命令
        /// </summary>
        /// <param name="request">医疗卡挂失命令</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>挂失结果</returns>
        public async Task<APIResult<bool>> Handle(LostMedicalCardCommand request, CancellationToken cancellationToken)
        {
            try
            {
                _logger.LogInformation($"开始处理医疗卡挂失，卡号: {request.CardNo}, 患者: {request.PatientName}");
                
                // 验证输入参数
                var validationResult = ValidateRequest(request);
                if (!validationResult.IsValid)
                {
                    return new APIResult<bool>
                    {
                        Code = APIEnums.Error,
                        Data = false,
                        Msg = validationResult.ErrorMessage
                    };
                }
                
                // 查找医疗卡记录
                var medicalCard = _medicalCardRepository.GetALL()
                    .FirstOrDefault(c => c.CardNo == request.CardNo && !c.IsDeleted);
                    
                if (medicalCard == null)
                {
                    return new APIResult<bool>
                    {
                        Code = APIEnums.Error,
                        Data = false,
                        Msg = "医疗卡不存在"
                    };
                }
                
                // 验证医疗卡是否属于该患者
                if (medicalCard.PatientId != request.PatientId)
                {
                    return new APIResult<bool>
                    {
                        Code = APIEnums.Error,
                        Data = false,
                        Msg = "医疗卡不属于该患者"
                    };
                }
                
                // 验证患者身份信息
                if (medicalCard.PatientName != request.PatientName || 
                    medicalCard.IdCard != request.IdCard || 
                    medicalCard.Phone != request.Phone)
                {
                    return new APIResult<bool>
                    {
                        Code = APIEnums.Error,
                        Data = false,
                        Msg = "患者身份信息不匹配"
                    };
                }
                
                // 检查医疗卡当前状态
                if (medicalCard.CardStatus == "已挂失")
                {
                    return new APIResult<bool>
                    {
                        Code = APIEnums.Error,
                        Data = false,
                        Msg = "该医疗卡已经挂失，无需重复操作"
                    };
                }
                
                if (medicalCard.CardStatus == "已注销")
                {
                    return new APIResult<bool>
                    {
                        Code = APIEnums.Error,
                        Data = false,
                        Msg = "该医疗卡已注销，无法挂失"
                    };
                }
                
                // 更新医疗卡状态为挂失
                medicalCard.CardStatus = "已挂失";
                medicalCard.Remarks = string.IsNullOrWhiteSpace(medicalCard.Remarks) 
                    ? $"挂失原因：{request.LostReason}" 
                    : $"{medicalCard.Remarks}；挂失原因：{request.LostReason}";
                
                if (!string.IsNullOrWhiteSpace(request.Remarks))
                {
                    medicalCard.Remarks += $"；备注：{request.Remarks}";
                }
                
                // 保存更新
                var result = _medicalCardRepository.Update(medicalCard);
                
                if (result > 0)
                {
                    _logger.LogInformation($"医疗卡挂失成功，卡号: {request.CardNo}, 患者: {request.PatientName}");
                    return new APIResult<bool>
                    {
                        Code = APIEnums.Success,
                        Data = true,
                        Msg = "医疗卡挂失成功"
                    };
                }
                else
                {
                    _logger.LogError($"医疗卡挂失失败，数据库更新失败，卡号: {request.CardNo}");
                    return new APIResult<bool>
                    {
                        Code = APIEnums.Error,
                        Data = false,
                        Msg = "医疗卡挂失失败，请稍后重试"
                    };
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"医疗卡挂失时发生异常，卡号: {request.CardNo}");
                return new APIResult<bool>
                {
                    Code = APIEnums.Error,
                    Data = false,
                    Msg = "医疗卡挂失失败，系统异常"
                };
            }
        }
        
        /// <summary>
        /// 验证请求参数
        /// </summary>
        /// <param name="request">请求参数</param>
        /// <returns>验证结果</returns>
        private (bool IsValid, string ErrorMessage) ValidateRequest(LostMedicalCardCommand request)
        {
            if (string.IsNullOrWhiteSpace(request.CardNo))
            {
                return (false, "医疗卡号不能为空");
            }
            
            if (request.PatientId <= 0)
            {
                return (false, "患者ID不能为空");
            }
            
            if (string.IsNullOrWhiteSpace(request.PatientName))
            {
                return (false, "患者姓名不能为空");
            }
            
            if (string.IsNullOrWhiteSpace(request.IdCard))
            {
                return (false, "身份证号不能为空");
            }
            
            if (!IsValidIdCard(request.IdCard))
            {
                return (false, "身份证号格式不正确");
            }
            
            if (string.IsNullOrWhiteSpace(request.Phone))
            {
                return (false, "联系电话不能为空");
            }
            
            if (!IsValidPhone(request.Phone))
            {
                return (false, "联系电话格式不正确");
            }
            
            return (true, string.Empty);
        }
        
        /// <summary>
        /// 验证身份证号格式
        /// </summary>
        /// <param name="idCard">身份证号</param>
        /// <returns>是否有效</returns>
        private bool IsValidIdCard(string idCard)
        {
            if (string.IsNullOrWhiteSpace(idCard))
                return false;
                
            // 简单的身份证号格式验证（15位或18位数字）
            return (idCard.Length == 15 || idCard.Length == 18) && 
                   idCard.All(c => char.IsDigit(c) || (idCard.Length == 18 && idCard[17] == 'X'));
        }
        
        /// <summary>
        /// 验证手机号格式
        /// </summary>
        /// <param name="phone">手机号</param>
        /// <returns>是否有效</returns>
        private bool IsValidPhone(string phone)
        {
            if (string.IsNullOrWhiteSpace(phone))
                return false;
                
            // 简单的手机号格式验证（11位数字，以1开头）
            return phone.Length == 11 && phone.StartsWith("1") && phone.All(char.IsDigit);
        }
    }
}